home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Scope / Scope Disk #078 (199x)(Scope PD)(US)[WB].zip / Scope Disk #078 (199x)(Scope PD)(US)[WB].adf / SD / sd.mod < prev   
Text File  |  1989-06-29  |  11KB  |  454 lines

  1. MODULE SD;
  2.  
  3. FROM Path    IMPORT    PathName;
  4. FROM printf     IMPORT     printf;
  5. FROM SYSTEM    IMPORT    ADR, ADDRESS, LONGWORD;
  6. FROM System    IMPORT    argc,argv;
  7. FROM AmigaDOS    IMPORT    FileHandle, FileLock, Lock, UnLock, 
  8.             AccessRead, Examine, ExNext, CurrentDir,
  9.             FileInfoBlockPtr, IoErr, ErrorNoMoreEntries, 
  10.             SigBreakCtrlC, BPTR, BSTR, Input, Read;
  11. FROM AmigaDOSExt    IMPORT    CommandLineInterfacePtr;
  12. FROM AmigaDOSProcess    IMPORT    ProcessPtr;
  13. FROM Memory    IMPORT    AllocMem, FreeMem, MemReqSet, MemPublic;
  14. FROM Strings    IMPORT    CopyString, ConcatString, StringLength,
  15.             CompareStringCAP, LocateSubString,
  16.             ConvStringToUpperCase, equal;
  17. FROM Tasks    IMPORT    TaskPtr, FindTask, CurrentTask;
  18.  
  19.  
  20. (*$D-*)
  21.  
  22. CONST
  23.     Version = '1.01c';
  24.     ClearLine = '\r\x9B\x4B\r';        
  25.     InvalidDeviceErr = '\r\x9B\x4B\r%s is not a valid device or directory.\n';
  26.     ExamineErr = '\r\x9B\x4B\r***ERROR in Examine()\n';
  27.     BreakErr = '\r\x9B\x4B\r *** BREAK ***\n';
  28.     MemErr = '\r\x9B\x4B\r***ERROR in allocating memory.\n';
  29.     LockErr = "\r\x9B\x4B\rCan't find %s\n";
  30.     GeneralErr = '\r\x9B\x4B\r***ERROR\n';
  31.  
  32.  
  33. TYPE
  34.     DirEntry = POINTER TO DirEntryRecord;
  35.     
  36.     DirEntryRecord = RECORD
  37.         DirName : ARRAY [0..30] OF CHAR;
  38.         next : DirEntry;
  39.     END;
  40.  
  41. VAR
  42.     fib : FileInfoBlockPtr;
  43.     mytask : TaskPtr;
  44.     processptr : ProcessPtr;
  45.     cliptr      : CommandLineInterfacePtr;
  46.     dirname : ARRAY [0..255] OF CHAR;
  47.     basename : ARRAY [0..30] OF CHAR;
  48.     pattern : ARRAY [0..30] OF CHAR;
  49.     null : ARRAY [0..0] OF CHAR;
  50.         found,dirtype : BOOLEAN;
  51.     exactset : BOOLEAN;
  52.     arg : LONGWORD;
  53.  
  54. PROCEDURE Usage();
  55. BEGIN
  56.     arg := ADR(Version);
  57.     printf('   Usage:  SD {device|directory|root}\n\
  58. \   Usage:  SD {pattern} [ON] {device|directory|root}\n\n\
  59. \t\33[33mS\33[m[earch] for \33[33mD\33[m[irectory]\n\
  60. \tIdentical to AmigaDOS CD command with an option to\n\
  61. \tsearch for a pattern.\n\n\
  62. \tBy David Czaya\t1988-Sept\n',arg);
  63.     HALT;
  64. END Usage;
  65.  
  66.  
  67. PROCEDURE CtrlC(): BOOLEAN;
  68. BEGIN
  69.     RETURN SigBreakCtrlC IN mytask^.tcSigRecvd
  70. END CtrlC;
  71.  
  72.  
  73. PROCEDURE Cleanup();
  74. BEGIN
  75.     IF CtrlC() THEN
  76.          printf(BreakErr,arg);
  77.     END;
  78.     
  79.     FreeMem(fib,SIZE(fib^));
  80.     HALT;
  81. END Cleanup;
  82.  
  83.  
  84. PROCEDURE MPTR(bptr: BPTR): ADDRESS;
  85. BEGIN
  86.     RETURN ADDRESS(bptr) * 4D;
  87. END MPTR;
  88.  
  89.  
  90. PROCEDURE matched(base,pattern: ARRAY OF CHAR; exact: BOOLEAN): BOOLEAN;
  91. VAR
  92.     str1,str2 : ARRAY [0..30] OF CHAR;
  93. BEGIN
  94.     IF NOT exact THEN
  95.         CopyString(str1,base);        (* we don't want to damage the *)
  96.         CopyString(str2,pattern);    (* originals, so we work on copies *)
  97.         ConvStringToUpperCase(str1);
  98.         ConvStringToUpperCase(str2);
  99.  
  100.         RETURN (LocateSubString(str1,str2,0,StringLength(str1)) # -1);
  101.     END;
  102.     RETURN (CompareStringCAP(pattern,base) = equal);
  103. END matched;
  104.  
  105.  
  106. PROCEDURE IsDevice(str: ARRAY OF CHAR): BOOLEAN;
  107. VAR
  108.     char : CHAR;
  109. BEGIN
  110.     char := str[StringLength(str)-1];
  111.     RETURN ((char = ':') OR (char = '/')); 
  112. END IsDevice;
  113.  
  114.  
  115. PROCEDURE IsDir(fib: FileInfoBlockPtr): BOOLEAN;
  116. BEGIN
  117.     RETURN (fib^.fibDirEntryType > 0D);
  118. END IsDir;
  119.  
  120.  
  121. (*$D+*)
  122. PROCEDURE TackOn(VAR FullPathName: ARRAY OF CHAR; 
  123.              ParentDir,DirName: ARRAY OF CHAR);
  124. BEGIN
  125.     CopyString(FullPathName,ParentDir);
  126.  
  127.     IF NOT IsDevice(FullPathName) THEN
  128.         ConcatString(FullPathName,'/');
  129.     END;
  130.     
  131.     ConcatString(FullPathName,DirName);
  132. END TackOn;
  133.  
  134.  
  135. PROCEDURE SetPathName(pathptr: ADDRESS; dirname: ARRAY OF CHAR);
  136. CONST
  137.     max = 80;
  138.     
  139.     PROCEDURE CSTRtoBSTR(VAR bstr: ADDRESS; 
  140.                      cstr: ARRAY OF CHAR;
  141.                      maxlen: CARDINAL); 
  142.     (* convert a Modula-2 (C) type string to address of BCPL string
  143.        path = ADDRESS of BSTR
  144.        pathname = Modula-2 type string array
  145.        maxlen = max length of the BSTR including length bytes  *)
  146.  
  147.     VAR
  148.         ptr : POINTER TO CHAR;
  149.         len,pos : CARDINAL;
  150.     BEGIN
  151.             ptr := bstr;
  152.         len := StringLength(cstr);
  153.             ptr^ := CHAR(len);
  154.             
  155.             pos := 0;
  156.         REPEAT        
  157.         INC(ADDRESS(ptr));
  158.         ptr^ := cstr[pos]; 
  159.         INC(pos);
  160.             UNTIL (pos = len) OR (pos = maxlen-1);
  161.     END CSTRtoBSTR;
  162.  
  163. BEGIN
  164.     CSTRtoBSTR(pathptr,dirname,max);
  165. END SetPathName;
  166.  
  167.  
  168. PROCEDURE GetCurrentDir(VAR dest: ARRAY OF CHAR): ADDRESS;
  169. VAR
  170.     pathptr : ADDRESS;
  171.  
  172.     PROCEDURE BSTRtoCSTR(VAR cstr: ARRAY OF CHAR; bstr: ADDRESS);
  173.        (* convert BCPL string to a Modula-2 (C) type string
  174.        bstr = ADDRESS of BSTR
  175.        cstr = string to hold the converted BSTR  *)
  176.        
  177.        VAR
  178.         ptr : POINTER TO CHAR;
  179.         len,pos : CARDINAL;
  180.        BEGIN
  181.         ptr := bstr;
  182.         len := ORD(ptr^);            (* length of string *)
  183.         FOR pos := 0 TO len-1 DO
  184.         INC(ADDRESS(ptr));        (* get string *)
  185.         cstr[pos] := ptr^;    
  186.         END;
  187.         cstr[len] := 0C;            (* tack on NULL *)
  188.        END BSTRtoCSTR;
  189. BEGIN
  190.     pathptr := MPTR(cliptr^.cliSetName);    (* get address of pathname *)
  191.     BSTRtoCSTR(dest,pathptr);        (* convert string to English *)
  192.     RETURN pathptr;                (* return ADDRESS of BSTR *)
  193.                         (* for later use *)
  194. END GetCurrentDir;
  195.  
  196.  
  197. PROCEDURE GetSysPath(VAR FullPath, BaseName: ARRAY OF CHAR; 
  198.              key: ARRAY OF CHAR; VAR dirtype: BOOLEAN): BOOLEAN;
  199. VAR
  200.     lock : FileLock;
  201.     fib : FileInfoBlockPtr;
  202. BEGIN
  203.     lock := Lock(ADR(key),AccessRead);
  204.     IF lock # 0D THEN
  205.     IF PathName(lock,FullPath) THEN
  206.         fib := AllocMem(SIZE(fib^),MemReqSet{MemPublic});
  207.         IF fib # NIL THEN
  208.             IF Examine(lock,fib^) THEN
  209.             dirtype := IsDir(fib);
  210.             CopyString(BaseName,fib^.fibFileName);
  211.             FreeMem(fib,SIZE(fib^));
  212.             UnLock(lock);
  213.             RETURN TRUE;
  214.         ELSE
  215.             printf(ExamineErr,arg);
  216.             FreeMem(fib,SIZE(fib^));
  217.             UnLock(lock);
  218.         END;                    (* IF Examine *)
  219.         ELSE
  220.             printf(MemErr,arg);
  221.         UnLock(lock);
  222.         END;                    (* IF fib *)
  223.     ELSE
  224.         printf(GeneralErr,arg);
  225.         UnLock(lock);
  226.     END;                        (* IF PathName *)
  227.     ELSE
  228.         arg := ADR(key);
  229.         printf(LockErr,arg);
  230.     END;                        (* IF lock *)
  231.     RETURN FALSE;
  232. END GetSysPath;
  233.  
  234.  
  235. PROCEDURE ScanDir(fib: FileInfoBlockPtr; VAR ParentDir, 
  236.           DirName: ARRAY OF CHAR);
  237. VAR
  238.     lock,
  239.     oldlock, newlock : FileLock;
  240.     pathptr : ADDRESS;
  241.     FullPathName : ARRAY [0..255] OF CHAR;
  242.     first, last : DirEntry; 
  243.     ok : BOOLEAN;
  244. BEGIN
  245.     first := NIL;
  246.     TackOn(FullPathName,ParentDir,DirName);
  247.  
  248.     lock := Lock(ADR(FullPathName),AccessRead);
  249.     ok := (lock # 0D) AND Examine(lock,fib^) AND ExNext(lock,fib^);
  250.     IF ok THEN
  251.     WHILE ok AND NOT CtrlC() AND NOT found AND
  252.         (IoErr() # ErrorNoMoreEntries) DO
  253.         IF IsDir(fib) THEN
  254.                  last := AllocMem(SIZE(last^),MemReqSet{MemPublic});
  255.             CopyString(last^.DirName,fib^.fibFileName);
  256.           last^.next := first;
  257.         first := last;
  258.         
  259.         IF exactset THEN
  260.             found := matched(fib^.fibFileName,argv^[1]^,TRUE);
  261.         ELSE
  262.             found := matched(fib^.fibFileName,argv^[1]^,FALSE);
  263.         END;
  264.  
  265.         IF found THEN    
  266.             TackOn(FullPathName,FullPathName,fib^.fibFileName);
  267.             newlock := Lock(ADR(FullPathName),AccessRead);
  268.             IF newlock # 0D THEN
  269.                 oldlock := CurrentDir(newlock);
  270.             UnLock(oldlock);
  271.             pathptr := MPTR(cliptr^.cliSetName);
  272.             SetPathName(pathptr,FullPathName);
  273.             ELSE
  274.                 printf(GeneralErr,arg);
  275.             END;                (* IF newlock *)
  276.         END;                    (* IF found *)
  277.         END;                    (* IF IsDir *)
  278.         ok := ExNext(lock,fib^);
  279.     END;                        (* WHILE *)
  280.         
  281.     WHILE first # NIL DO
  282.         IF NOT CtrlC() AND NOT found THEN
  283.         ScanDir(fib,FullPathName,first^.DirName);
  284.         END;
  285.         
  286.         last := first;
  287.         first := first^.next;
  288.         FreeMem(last,SIZE(last^));
  289.     END;
  290.     END;
  291.     UnLock(lock);
  292. END ScanDir;
  293. (*$D-*)
  294.  
  295.  
  296. PROCEDURE OneArg(fib: FileInfoBlockPtr; dirname: ARRAY OF CHAR);
  297.     (* This is more code than would be necessary if I used
  298.        ScanDir(), but it's different enough that all the
  299.        IF/THENs would make ScanDir() unreadable, so...  *)
  300. VAR
  301.     pathptr : ADDRESS;
  302.     lock,
  303.     newlock,oldlock : FileLock;
  304. BEGIN
  305.     lock := Lock(ADR(dirname),AccessRead);
  306.     IF lock # 0D THEN
  307.     IF Examine(lock,fib^) THEN
  308.         IF IsDir(fib) THEN
  309.         newlock := Lock(ADR(dirname),AccessRead);
  310.         IF newlock # 0D THEN
  311.             oldlock := CurrentDir(newlock);
  312.             UnLock(oldlock);
  313.             UnLock(lock);
  314.             pathptr := MPTR(cliptr^.cliSetName);
  315.             SetPathName(pathptr,dirname);
  316.         ELSE
  317.             printf(GeneralErr,arg);
  318.             UnLock(lock);
  319.         END;
  320.         ELSE
  321.         arg := ADR(dirname);
  322.         printf(InvalidDeviceErr,arg);
  323.         UnLock(lock);
  324.         END;                    (* IF IsDir *)
  325.     ELSE
  326.         printf(ExamineErr,arg);
  327.         UnLock(lock);
  328.     END;                        (* IF Examine *)
  329.     ELSE
  330.         arg := ADR(dirname);
  331.         printf(LockErr,arg);
  332.     END;                        (* IF lock *)
  333. END OneArg;
  334.  
  335.  
  336. PROCEDURE NoArgs();
  337. VAR
  338.     pathptr : ADDRESS;
  339. BEGIN
  340.     arg := ADR(dirname);
  341.     
  342.     pathptr := GetCurrentDir(dirname);    (* pathptr not needed here *)
  343.     printf('%s\n',arg);
  344. END NoArgs;
  345.  
  346.  
  347. PROCEDURE Init();
  348. BEGIN
  349.     mytask := FindTask(CurrentTask);
  350.     processptr := ProcessPtr(mytask);
  351.     cliptr := MPTR(processptr^.prCLI);
  352.  
  353.     fib := AllocMem(SIZE(fib^),MemReqSet{MemPublic});
  354.  
  355.     IF fib = NIL THEN
  356.         printf(MemErr,arg);
  357.     HALT;
  358.     END;
  359. END Init;
  360.  
  361.  
  362. PROCEDURE ReadDir();
  363. VAR
  364.     fh : FileHandle;
  365.     len : CARDINAL;
  366.     dirtype : BOOLEAN;            (* TRUE if directory *)
  367. BEGIN
  368.     printf('DIR: ',arg);
  369.     fh := Input();
  370.     len := Read(fh,ADR(dirname),128);        (* should change to 256 *)
  371.     IF dirname[0] = 12C THEN
  372.     Init();
  373.     NoArgs();
  374.     Cleanup();
  375.     ELSIF dirname[0] = '?' THEN
  376.     ReadDir();
  377.     ELSIF dirname[0] = '-' THEN
  378.     Usage();
  379.     ELSE
  380.     dirname[len-1] := 0C;
  381.  
  382.     Init();
  383.     IF GetSysPath(dirname,basename,dirname,dirtype) THEN
  384.             IF dirtype THEN
  385.             OneArg(fib,dirname);
  386.         ELSE
  387.             arg := ADR(dirname);
  388.             printf(InvalidDeviceErr,arg);
  389.         END;
  390.     END;
  391.     END;
  392. END ReadDir;
  393.  
  394.  
  395. BEGIN
  396.     CASE argc OF
  397.     1 : Init();
  398.         NoArgs();
  399.             Cleanup(); |            (* just print current dir *)
  400.  
  401.     2 : IF argv^[1]^[0] = '-' THEN
  402.         Usage();
  403.         ELSIF argv^[1]^[0] = '?' THEN
  404.         printf('\t(-h for Usage)\n',arg);
  405.         ReadDir();
  406.         Cleanup();
  407.         ELSE
  408.         Init();
  409.         IF GetSysPath(dirname,basename,argv^[1]^,dirtype) THEN
  410.             IF dirtype THEN
  411.                 OneArg(fib,dirname);
  412.             ELSE
  413.                 arg := ADR(dirname);
  414.                 printf(InvalidDeviceErr,arg);
  415.             END;
  416.         END;
  417.         Cleanup();
  418.         END; |    
  419.     3 : IF (CompareStringCAP(argv^[2]^,"ON") = equal) THEN
  420.             Usage();
  421.         END; |    
  422.     4 : IF (CompareStringCAP(argv^[2]^,"ON") = equal) THEN
  423.             argv^[2] := argv^[3];
  424.         END;
  425.     ELSE
  426.         Usage();
  427.     END;
  428.  
  429.     Init();
  430.     null := '';
  431.     found := FALSE;
  432.     exactset := FALSE;
  433.     
  434.     IF (argv^[1]^[0] = '~') THEN
  435.     argv^[1] := ADDRESS(argv^[1]) + 1D;
  436.     IF (argv^[1]^[0] # '~') THEN
  437.         exactset := TRUE;
  438.         END;
  439.     END;
  440.     
  441.     IF GetSysPath(dirname,basename,argv^[2]^,dirtype) THEN
  442.         IF dirtype THEN
  443.         arg := ADR(dirname);
  444.         printf('Searching %s',arg);
  445.             ScanDir(fib,dirname,null);
  446.         printf(ClearLine,arg);
  447.         ELSE
  448.         arg := ADR(dirname);
  449.         printf(InvalidDeviceErr,arg);
  450.         END;
  451.     END;
  452.     Cleanup();
  453. END SD.
  454.